package com.seaboxdata.jt809.common.util;

/**
 * @author
 * @create 2020-10-21 9:16
 * 判断经纬度是否在大鹏新区范围内
 **/
public class LonLatUtil {
    public static boolean isPtInPoly(Point point, Point[] points) {
        if (points.length < 3) {
            return false;
        }
        Range range = getRange(points);
        int len = points.length;
        double lon1, lon2, lat1, lat2, lon;
        int sum = 0, itrue = 0;
        for (int i = 0; i < len; i++) {
            if ((point.lon == points[i].lon && point.lat == points[i].lat)) {
                return true;
            }
            if (point.lon == range.minLon || point.lon == range.maxLon) {
                return point.lat == range.minLat || point.lat == range.maxLat;
            }
            if (i == len - 1) {
                lon1 = points[i].lon;
                lat1 = points[i].lat;
                lon2 = points[0].lon;
                lat2 = points[0].lat;
            } else {
                lon1 = points[i].lon;
                lat1 = points[i].lat;
                lon2 = points[i + 1].lon;
                lat2 = points[i + 1].lat;
            }
            if (Math.abs(lat1 - lat2) != 0) {//水平的线不需要判断
                if ((point.lat >= lat1 && point.lat < lat2) || (point.lat >= lat2 && point.lat < lat1)) {
//计算直线和多边形相交点的lon坐标：
                    lon = lon1 - ((lon1 - lon2) * (lat1 - point.lat)) / (lat1 - lat2);
//如果待判断点在相交点的右侧，则以待判定点为基点，向左的射线与此多边形的边相交，计数器加一
                    if (lon < point.lon)
                        sum++;
                    else if (lon == point.lon)
                        itrue++;
                }
            }
        }
//只有当以待判定点作为基点，向左的射线与整个多边形的所有边相交的个数为奇数时，此点则判定在多边形内，否在在外
        return (sum % 2 != 0) || (itrue > 0);
    }

    private static Range getRange(Point[] points) {
        Range range = new Range(180d, -180d, 90d, -90d);
        for (Point point : points) {
            if (point.lon < range.minLon) {
                range.minLon = point.lon;
            } else if (point.lon > range.maxLon) {
                range.maxLon = point.lon;
            }
            if (point.lat < range.minLat) {
                range.minLat = point.lat;
            } else if (point.lat > range.maxLat) {
                range.maxLat = point.lat;
            }
        }
        return range;
    }

    public static class Point {
        double lon;
        double lat;

        public Point(double lon, double lat) {
            this.lon = lon;
            this.lat = lat;
        }
    }

    public static class Range {
        double minLon;
        double maxLon;
        double minLat;
        double maxLat;

        private Range(double minLon, double maxLon, double minLat, double maxLat) {
            this.minLon = minLon;
            this.maxLon = maxLon;
            this.minLat = minLat;
            this.maxLat = maxLat;
        }
    }


    public static void main(String[] args) {
        double[][] lonLats =
                {{114.502326, 22.671276},
                {114.5963682, 22.65788301},
                {114.6253057, 22.50513332},
                {114.5065689, 22.44014054},
                {114.3466708, 22.6012205},
                {114.346231, 22.606963},
                {114.335217, 22.60711},
                {114.335108, 22.628361},
                {114.374682, 22.64477251},
                {114.384271, 22.64417},
                {114.408915, 22.656745},
                {114.448514, 22.672634},
                {114.4616321, 22.6777162},
                {114.502326, 22.671276}};
        Point[] points = new Point[14];
        int i = 0;
        for (double[] lonlat : lonLats) {
            points[i++] = new Point(lonlat[0], lonlat[1]);
        }
        Point point1 = new Point(114.406058, 22.614545);
        Point point2 = new Point(114.397886, 22.614096);
        Point point3 = new Point(114.400221, 22.611296);
        Point point4 = new Point(114.416355 , 22.621178);
        Point point5 = new Point(114.418416, 22.643734);

        Point point6 = new Point(114.397978, 22.613991);
        Point point7 = new Point(114.400171, 22.649699);
        Point point8 = new Point(114.503355, 22.611290);
        Point point9 = new Point(114.512890, 22.540723);
        Point point10 = new Point(114.399552, 22.614068);
        Point point11 = new Point(114.351881, 22.608690);
        System.out.println(isPtInPoly(point1, points));
        System.out.println(isPtInPoly(point2, points));
        System.out.println(isPtInPoly(point3, points));
        System.out.println(isPtInPoly(point4, points));
        System.out.println(isPtInPoly(point5, points));
        System.out.println(isPtInPoly(point6, points));
        System.out.println(isPtInPoly(point7, points));
        System.out.println(isPtInPoly(point8, points));
        System.out.println(isPtInPoly(point9, points));
        System.out.println(isPtInPoly(point10, points));
        System.out.println(isPtInPoly(point11, points));
    }
}
